package bsr.basara.autodata.util;

/**
 * 趋势线工具
 * ◞◜◝◟
 *
 * @author basara
 */
public class TrendUtils {

    public static void main(String[] args) {


    }

    /**
     * 线性
     *
     * @param x
     * @return
     */
    public static Double linear(double x, int trend) {
        switch (trend) {
            case 1:
                return x;
            case 2:
                return -x + 1;
            default:
                return 0.0;
        }
    }

    /**
     * 二次方
     *
     * @param x
     * @return
     */
    public static Double quadratic(double x, int trend) {
        switch (trend) {
            case 1:
                return Math.pow(x, 2);
            case 2:
                return -Math.pow(x - 1, 2) + 1;
            case 3:
                return -Math.pow(x, 2) + 1;
            case 4:
                return Math.pow(x - 1, 2);
            default:
                return x;
        }
    }

    /**
     * 三次方
     *
     * @param x
     * @return
     */
    public static Double cubic(double x, int trend) {
        switch (trend) {
            case 1:
                return Math.pow(x, 3);
            case 2:
                return Math.pow(x - 1, 3) + 1;
            case 3:
                return -Math.pow(x, 3) + 1;
            case 4:
                return -Math.pow(x - 1, 3);
            default:
                return x;
        }
    }

    /**
     * 四次方
     *
     * @param x
     * @return
     */
    public static Double quartic(double x, int trend) {
        switch (trend) {
            case 1:
                return Math.pow(x, 4);
            case 2:
                return -Math.pow(x - 1, 4) + 1;
            case 3:
                return -Math.pow(x, 4) + 1;
            case 4:
                return Math.pow(x - 1, 4);
            default:
                return x;
        }
    }

    /**
     * 五次方
     *
     * @param x
     * @return
     */
    public static Double quintic(double x, int trend) {
        switch (trend) {
            case 1:
                return Math.pow(x, 5);
            case 2:
                return Math.pow(x - 1, 5) + 1;
            case 3:
                return -Math.pow(x, 5) + 1;
            case 4:
                return -Math.pow(x - 1, 5);
            default:
                return x;
        }
    }

    /**
     * 正弦
     *
     * @param x
     * @return
     */
    public static Double sinusoidal(double x, int trend) {
        switch (trend) {
            case 1:
                return 1 - Math.cos((x * Math.PI) / 2);
            case 2:
                return Math.sin((x * Math.PI) / 2);
            case 3:
                return Math.cos((x * Math.PI) / 2);
            case 4:
                return 1 - Math.sin((x * Math.PI) / 2);
            default:
                return x;
        }
    }

    /**
     * 指数
     *
     * @param x
     * @return
     */
    public static Double exponential(double x, int trend) {
        switch (trend) {
            case 1:
                return x == 0 ? 0 : Math.pow(1024, x - 1);
            case 2:
                return x == 1 ? 1 : 1 - Math.pow(2, -10 * x);
            case 3:
                return x == 0 ? 1 : 1 - Math.pow(2, 10 * (x - 1));
            case 4:
                return x == 1 ? 0 : Math.pow(1024, -x);
            default:
                return x;
        }
    }

    /**
     * 循环函数
     *
     * @param x
     * @return
     */
    public static Double circular(double x, int trend) {
        switch (trend) {
            case 1:
                return 1 - Math.sqrt(1 - x * x);
            case 2:
                return Math.sqrt(1 - Math.pow(x - 1, 2));
            case 3:
                return Math.sqrt(1 - x * x);
            case 4:
                return 1 - Math.sqrt(1 - (x - 1) * (x - 1));
            default:
                return x;
        }
    }

    /**
     * 弹性
     *
     * @param x
     * @return
     */
    public static Double elastic(double x, int trend) {
        double si;
        double a = 0.1;
        double p = 0.1;

        if (a < 1) {
            a = 1;
            si = p / 4;
        } else {
            si = (p * Math.asin(1 / a)) / (2 * Math.PI);
        }

        switch (trend) {
            case 1:
                return x == 0 ? 0 : -(a * Math.pow(2, 10 * (x -= 1)) * Math.sin(((x - si) * (2 * Math.PI)) / p));
            case 2:
                return x == 0 ? 0 : a * Math.pow(2, -10 * x) * Math.sin(((x - si) * (2 * Math.PI)) / p) + 1;
            case 3:
                return x == 0 ? 1 : (a * Math.pow(2, 10 * (x -= 1)) * Math.sin(((x - si) * (2 * Math.PI)) / p)) + 1;
            case 4:
                return x == 0 ? 1 : -a * Math.pow(2, -10 * x) * Math.sin(((x - si) * (2 * Math.PI)) / p);
            default:
                return x;
        }
    }

    /**
     * 回退
     *
     * @param x
     * @return
     */
    public static Double back(double x, int trend) {
        double s = 1.70158;

        switch (trend) {
            case 1:
                return x * x * ((s + 1) * x - s);
            case 2:
                return (x - 1) * (x - 1) * ((s + 1) * (x - 1) + s) + 1;
            case 3:
                return -x * x * ((s + 1) * x - s) + 1;
            case 4:
                return -(x - 1) * (x - 1) * ((s + 1) * (x - 1) + s);
            default:
                return x;
        }

    }

    /**
     * 弹跳
     *
     * @param x
     * @return
     */
    public static Double bounce(double x, int trend) {
        switch (trend) {
            case 1:
                return 1 - bounceOut(1 - x);
            case 2:
                return bounceOut(x);
            case 3:
                return bounceOut(1 - x);
            case 4:
                return -bounceOut(x) + 1;
            default:
                return x;
        }
    }

    public static Double bounceOut(double x) {
        if (x < 1 / 2.75) {
            return 7.5625 * x * x;
        } else if (x < 2 / 2.75) {
            return 7.5625 * (x -= 1.5 / 2.75) * x + 0.75;
        } else if (x < 2.5 / 2.75) {
            return 7.5625 * (x -= 2.25 / 2.75) * x + 0.9375;
        } else {
            return 7.5625 * (x -= 2.625 / 2.75) * x + 0.984375;
        }
    }

}
